package com.wxb.hello.activemq.config;

import com.wxb.hello.activemq.consumer.EmailConsumer;
import com.wxb.hello.activemq.consumer.MessageReceiver;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.RedeliveryPolicy;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.listener.SimpleMessageListenerContainer;

import java.util.ArrayList;
import java.util.List;

/**
 * describe:
 *
 * @author : 王校兵
 * @version : v1.0
 * @time : 2017/7/27  14:59
 */
@Configuration
public class ReDeliveryConfig {

    @Value("${spring.activemq.broker-url}")
    private String host;

    /**
     * 创建activeMQ connection factory
     * ConnectionFactory，用于jms client获取与jms provider的连接。
     * 不同的jms产品，对这个接口有不同的实现，比如说ActiveMQ，这个接口的实现类是ActiveMQConnectionFactory
     */
    @Bean
    public ActiveMQConnectionFactory connectionFactory() {
        ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
        factory.setBrokerURL(host);
        factory.setRedeliveryPolicy(activeMQRedeliveryPolicy());
        List<String> trustList = new ArrayList<>();
        trustList.add("com.wxb.hello.activemq.repository");
        factory.setTrustedPackages(trustList);
        return factory;
    }

    /**
     * 创建消息监听容器 消息接收监听器用于异步接收消息
     */
    @Bean
    public SimpleMessageListenerContainer jmsContainerOne() {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();

        //设置activemq connection factory
        container.setConnectionFactory(connectionFactory());

        //设置消费者
        container.setMessageListener(getMessageReceiver());

        //Destination，是消息源，对发送者来说，就是消息发到哪里；
        // 对接收者来说，就是从哪里取消息。Destination有2个子接口，Queue和Topic。
        container.setDestination(queue());

        //
        container.setSessionTransacted(true);

        return container;
    }

    /**
     * 创建队列
     */
    @Bean
    public ActiveMQQueue queue() {
        return new ActiveMQQueue("my-queue");
    }

    /**
     * 创建消费者
     */
    @Bean
    public EmailConsumer getMessageReceiver() {
        return new EmailConsumer();
    }

    /**
     * 定义ReDelivery(重发机制)机制 ，重发时间间隔是100毫秒，最大重发次数是3次
     */
    @Bean
    public RedeliveryPolicy activeMQRedeliveryPolicy() {
        RedeliveryPolicy policy = new RedeliveryPolicy();

        //是否在每次尝试重新发送失败后,增长这个等待时间
        policy.setUseExponentialBackOff(true);

        //重发次数,默认为6次
        policy.setMaximumRedeliveries(3);

        //重发时间间隔,默认为1秒
        policy.setInitialRedeliveryDelay(1000);

        //第一次失败后重新发送之前等待500毫秒,第二次失败再等待500 * 2毫秒,这里的2就是value
        policy.setBackOffMultiplier(2);

        //最大传送延迟，只在useExponentialBackOff为true时有效（V5.5），假设首次重连间隔为10ms，倍数为2，那么第
        //二次重连时间间隔为 20ms，第三次重连时间间隔为40ms，当重连时间间隔大的最大重连时间间隔时，以后每次重连时间间隔都为最大重连时间间隔。
//        policy.setMaximumRedeliveries(1000);

        return policy;
    }
}
